
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       mb_mission_change_detector.c
  * @author     baiyang
  * @date       2022-10-5
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include "mb_mission_change_detector.h"

#include<string.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/
static struct Mission_ChangeDetector mission_change_detector;
/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
// check for changes to mission. returns true if mission has been changed since last check
bool MissionChangeDetector_check_for_mission_change()
{
    // check if mission has been updated
    const uint32_t change_time_ms = mission_last_change_time_ms();
    const bool update_time_changed = (change_time_ms != mission_change_detector.mis_change_detect.last_change_time_ms);

    // check if active command index has changed
    const uint16_t curr_cmd_idx = mission_get_current_nav_index();
    const bool curr_cmd_idx_changed = (curr_cmd_idx != mission_change_detector.mis_change_detect.curr_cmd_index);

    // no changes if neither mission update time nor active command index has changed
    if (!update_time_changed && !curr_cmd_idx_changed) {
        return false;
    }

    // the mission has been updated (but maybe not changed) and/or the current command index has changed
    // check the contents of the next three commands to ensure they have not changed
    // and update storage so we can detect future changes

    bool cmds_changed = false;  // true if upcoming command contents have changed

    // retrieve cmds from mission and compare with mis_change_detect
    uint8_t num_cmds = 0;
    uint16_t cmd_idx = curr_cmd_idx;
    struct Mission_Command cmd[mis_change_detect_cmd_max];
    while ((num_cmds < ARRAY_SIZE(cmd)) && mission_get_next_nav_cmd(cmd_idx, &cmd[num_cmds])) {
        num_cmds++;
        if ((num_cmds > mission_change_detector.mis_change_detect.cmd_count) || !(memcmp(&cmd[num_cmds-1], &mission_change_detector.mis_change_detect.cmd[num_cmds-1], sizeof(struct Mission_Command)) == 0)) {
            cmds_changed = true;
            mission_change_detector.mis_change_detect.cmd[num_cmds-1] = cmd[num_cmds-1];
        }
        cmd_idx = cmd[num_cmds-1].index+1;
    }

    // mission has changed if number of upcoming commands does not match mis_change_detect
    if (num_cmds != mission_change_detector.mis_change_detect.cmd_count) {
        cmds_changed = true;
    }

    // update mis_change_detect with last change time, command index and number of commands
    mission_change_detector.mis_change_detect.last_change_time_ms = change_time_ms;
    mission_change_detector.mis_change_detect.curr_cmd_index = curr_cmd_idx;
    mission_change_detector.mis_change_detect.cmd_count = num_cmds;

    // mission has changed if upcoming command contents have changed without the current command index changing
    return cmds_changed && !curr_cmd_idx_changed;
}

/*------------------------------------test------------------------------------*/


